<template>
  <div class="page-container">
    <s-table-layout :hideSearch="isHideSearch" :page-key="pageKey">
      <template #form>
        <z-form :model="formData" label-width="80px">
          <s-form-items :configs="formItems" :form-data="formData" :showActions="true" @search="getTableData(true)">
            <template #targetCodeList>
              <huiyan-area
                v-if="quoteObjectEnum.manage === formData.targetType"
                v-model="formData.targetCodeList"
                :collapse="true"
                multiple
              ></huiyan-area>
              <huiyan-center
                v-else-if="quoteObjectEnum.center === formData.targetType"
                v-model="formData.targetCodeList"
                multiple
                :collapse="true"
                immediate-fetch
                api="/pangu-quota/common/site/queryTransfer"
                :params="{
                  secondCategoryCodeList: [10, 12]
                }"
              ></huiyan-center>
              <huiyan-site
                v-else-if="quoteObjectEnum.site === formData.targetType"
                v-model="formData.targetCodeList"
                multiple
                :collapse="true"
                immediate-fetch
              ></huiyan-site>
              <z-select
                v-else
                v-model="formData.targetCodeList"
                placeholder="请先选择对象类型"
                :disabled="formData.targetType"
              ></z-select>
            </template>
          </s-form-items>
        </z-form>
      </template>
      <template #page-title>报价信息</template>
      <template #tools>
        <z-button v-if="isEdit" class="z-icon-plus" type="primary" @click="handleAddObj">新增</z-button>
        <z-button v-if="isEdit" type="primary" @click="handleBatchSet">批量设置</z-button>
        <z-button v-if="isEdit" class="mg-r8" @click="handleImport">批量导入</z-button>
        <s-download-button
          :columns="getExportColumns()"
          :file-name="fileName"
          :fields="fields"
          :on-confirm="handleExport"
          confirm-layout="fields,fileName"
          >导出</s-download-button
        >
      </template>
      <template #table>
        <s-table
          ref="ruleTableRef"
          :adapter="tableAjax"
          show-fixed
          :show-index="false"
          :span-method="arraySpanMethod"
          :columns="tableColumns"
          :data.sync="tableData"
          :show-checkbox="false"
          :show-operation="isEdit"
          :page-size="50"
          :pageSizes="[10, 20, 50]"
        >
          <template #checkboxHeader>
            <z-checkbox v-model="isAllSelected" @change="handleAllSelected"></z-checkbox>
          </template>
          <template #checkbox="{row,$index}">
            <z-checkbox v-model="row.isSelected" @change="val => handleItemChecked(val, row, $index)"></z-checkbox>
          </template>
          <!-- <template #index="{$index}">
            <span>{{ getOrderByRowIndex($index, spanArr) }}</span>
          </template> -->
          <template #targetName="{row}">
            <div class="is-left">
              <z-tag :type="row.ruleType === quoteRuleTypeEnum.long ? 'success' : 'warning'">{{
                row.ruleTypeDesc
              }}</z-tag>
              <!-- <z-tag v-if="row.quoteStatus === 0" type="info">{{ row.quoteStatusDesc }}</z-tag> -->
              <span class="target-name">{{ row.targetName }}</span>
            </div>
          </template>
          <template #targetCode="{row}">
            <span v-if="row.targetCode === '0'">-</span>
            <span v-else>{{ row.targetCode }}</span>
          </template>
          <template #errorRateDesc="{row, $index}">
            <div v-if="isEdit" class="cell-row">
              <div class="table-cell startRate-cell">
                <z-input-number
                  v-model="row.errorRateStart"
                  :class="{ error: validateField(row, 'errorRateStart') }"
                  :precision="2"
                  :min="0"
                  :max="100"
                  size="small"
                  :controls="false"
                  placeholder="开始值"
                  :disabled="true"
                ></z-input-number>
                <span class="cell-divider"> ~ </span>
                <z-input-number
                  v-model="row.errorRateEnd"
                  :class="{ error: validateField(row, 'errorRateEnd') }"
                  :precision="2"
                  :min="0"
                  :max="100"
                  size="small"
                  :controls="false"
                  placeholder="结束值"
                  :disabled="!isEdit"
                  @change="handleEndWeightChange(false, row, $index)"
                ></z-input-number>
              </div>
              <i
                v-if="isShowDelete($index)"
                class="z-icon-delete"
                size="16"
                @click="handleEndWeightChange(true, row, $index)"
              ></i>
            </div>
            <div v-else class="table-cell startRate-cell">
              <span>{{ row.errorRateStart }}</span>
              <span class="cell-divider"> ~ </span>
              <span>{{ row.errorRateEnd }}</span>
            </div>
          </template>
          <template #coefficient="{row}">
            <z-input-number
              v-if="isEdit"
              v-model="row.coefficient"
              :class="{ error: validateField(row, 'coefficient') }"
              :precision="2"
              :min="0.01"
              :max="100"
              size="small"
              :controls="false"
              placeholder="请输入"
              @change="saveTableData"
            ></z-input-number>
            <span v-else>{{ row.coefficient }}</span>
          </template>
          <template #executeDateDesc="{row}">
            <div v-if="isEdit" class="table-cell">
              <z-date-picker
                v-model="row.effectiveTimeDesc"
                :class="{ error: validateField(row, 'effectiveTimeDesc') }"
                :clearable="false"
                value-format="yyyy-MM-dd"
                placeholder="请选择开始时间"
                :picker-options="pickerStartOptions(row)"
                @change="saveTableData"
              >
              </z-date-picker>
              <span>&nbsp;至&nbsp;</span>
              <z-date-picker
                v-model="row.expireTimeDesc"
                :class="{ error: validateField(row, 'expireTimeDesc') }"
                :clearable="false"
                value-format="yyyy-MM-dd"
                placeholder="长期"
                :picker-options="pickerEndOptions(row)"
                @change="saveTableData"
              >
              </z-date-picker>
            </div>
            <span v-else>{{ `${row.effectiveTimeDesc} 至 ${row.expireTimeDesc || '长期'}` }}</span>
          </template>
          <template #default="{row}">
            <z-button type="text" @click="handleDelete(row)">删除</z-button>
          </template>
        </s-table>
      </template>
    </s-table-layout>
    <!-- 目的地选择 -->
    <quote-destination
      ref="destinationRef"
      :isBatchSiteQuery="true"
      :isBuQuery="true"
      :centerParams="{
        secondCategorys: [10, 12]
      }"
      :canSelectTypes="canSelectTypes"
      :defaultSelectType="defaultSelectType"
      :quoteBasicInfo="quoteBasicInfo"
      :defaultMANAGESelectList="defaultMANAGESelectList"
      :defaultCENTERSelectList="defaultCENTERSelectList"
      :defaultSITESelectList="defaultSITESelectList"
      :otherMANAGESelectList="otherMANAGESelectList"
      :otherCENTERSelectList="otherCENTERSelectList"
      :otherSITESelectList="otherSITESelectList"
      :selectDescList="selectDescList"
      @confirmSelect="confirmRegionSelect"
    ></quote-destination>
    <!-- 批量设置 -->
    <batch-set-form
      ref="batchSetFormRef"
      :hasTempData="hasTempData"
      :quoteBasicInfo="quoteBasicInfo"
      @success="handleBatchData"
    ></batch-set-form>
    <!-- 报价导入 -->
    <import-sheet
      ref="refImportSheet"
      feeType="packageSurchargeRatio"
      :importExecuteFun="importCoefficient"
      downLoadFileName="包补收系数导入模板.xlsx"
      :importParams="{
        batchNo: batchNo || quoteId,
        type: 2
      }"
      @success="handleImportSuccess"
    ></import-sheet>
  </div>
</template>
<script>
import importSheet from '@/views/pages/feePolicyManage/add/volumeDimensional/components/importSheet'
import { descRegionTypeEnum } from '@/quoteComps/quoteConfig/option'
import {
  handleWeightRangeData,
  getOrderByRowIndex,
  getGroupIndexes,
  getSpanPosition
} from '@/views/pages/feePolicyManage/add/addQuote/index.js'
import {
  importCoefficient,
  exportPackageRuleTarget,
  queryPackageRuleTarget,
  addBagThrowTarget,
  removeBagThrowTarget,
  modifyBagThrowTarget
} from '@/api/quoteRule'
import { quoteObjectEnum, quoteRuleTypeEnum } from '@/views/quoteOption.js'
import { cloneDeep, dayjs } from '@zto/z-utils-es'
import { tableConfigKey } from '@/config/common'
import quoteDestination from '../quoteDestination/index.vue'
import batchSetForm from '../batchSetForm/index.vue'
import { columns } from './config/columns'

export default {
  components: { quoteDestination, batchSetForm, importSheet },
  props: {
    // 是否展示搜索，详情页面展示
    isHideSearch: {
      type: Boolean,
      default: true
    },
    editType: {
      type: String,
      default: 'edit'
    }
  },
  data() {
    const { modifyType, id, batchNo } = this.$route.query
    return {
      batchNo,
      quoteId: id,
      modifyType,
      pageKey: `${tableConfigKey}-packingCoefficient-rulesTable`,
      quoteObjectEnum,
      importCoefficient,
      editable: true,
      formData: {
        targetType: '',
        targetCodeList: []
      },
      tableData: [],
      spanArr: [],
      quoteBasicInfo: {},
      canSelectTypes: [descRegionTypeEnum.manage, descRegionTypeEnum.site, descRegionTypeEnum.center],
      defaultSelectType: descRegionTypeEnum.manage,
      defaultMANAGESelectList: [], // 默认选择的管区
      defaultCENTERSelectList: [], // 默认选择的中心
      defaultSITESelectList: [], // 默认选择的网点
      otherMANAGESelectList: [], // 其他已选择的管区
      otherCENTERSelectList: [], // 其他已选择的中心
      otherSITESelectList: [], // 其他已选择的网点
      selectDescList: [],
      quoteRuleTypeEnum,
      groupedSelections: [],
      isAllSelected: false,
      fields: { sortable: true, col: 2 },
      fileName: {
        default: '收费政策管理-包补收系数',
        rules: [
          { required: true, message: '请输入文件名' },
          { max: 20, message: '文件名不能超过20个字符', trigger: 'blur' }
        ]
      }
    }
  },
  computed: {
    isEdit() {
      return this.modifyType !== 'view' && this.editType !== 'view'
    },
    formItems() {
      return [
        {
          label: '对象类型',
          prop: 'targetType',
          itemType: 'select',
          options: [
            {
              label: '管区',
              value: quoteObjectEnum.manage
            },
            {
              label: '中心',
              value: quoteObjectEnum.center
            },
            {
              label: '网点',
              value: quoteObjectEnum.site
            }
          ],
          clearable: false,
          onchange: () => {
            this.formData.targetCodeList = []
          }
        },
        {
          label: '对象名称',
          prop: 'targetCodeList',
          showSlot: true,
          multiple: true,
          collapseTags: true
        }
      ]
    },
    columns() {
      return this.isEdit ? columns : columns.filter(item => !['checkbox'].includes(item.prop))
    },
    tableColumns() {
      return this.columns.filter(item => !['ruleTypeDesc'].includes(item.prop))
    },
    // 包含临时报价
    hasTempData() {
      // 按照分组后的数据进行判断
      return this.groupedSelections.some(item => item.ruleType === quoteRuleTypeEnum.temp)
    }
  },
  mounted() {
    this.getTableData(true)
  },
  methods: {
    getOrderByRowIndex,
    pickerStartOptions(row) {
      return {
        disabledDate(time) {
          return dayjs(time).isAfter(dayjs(row.expireTimeDesc))
        }
      }
    },
    pickerEndOptions(row) {
      return {
        disabledDate(time) {
          // 小于开始时间
          return dayjs(time).isBefore(dayjs(row.effectiveTimeDesc))
        }
      }
    },
    getExportColumns() {
      return this.columns
    },
    async handleExport(exportParams, type) {
      const { fields, fileName } = exportParams
      let params = {
        batchNo: this.batchNo,
        fileName,
        fields: fields.map(item => item.prop)
      }
      if (this.modifyType === 'add') {
        params = {
          ...params,
          batchNo: this.quoteId
        }
      }
      await exportPackageRuleTarget(params)
    },
    handleImportSuccess() {
      this.getTableData(true)
    },
    getTableData(resetPage = false) {
      this.isAllSelected = false
      this.$refs.ruleTableRef.fetchData(resetPage)
    },
    handleAddObj() {
      this.$nextTick(() => {
        this.$refs.destinationRef.open()
      })
    },
    // 目的地选择确认
    async confirmRegionSelect({ dataList, regionType, ruleType }) {
      if (!dataList.length && regionType !== '0') return
      const getTargetType = () => {
        if (regionType === descRegionTypeEnum.manage || regionType === '0') {
          return quoteObjectEnum.manage
        }
        if (regionType === descRegionTypeEnum.center) {
          return quoteObjectEnum.center
        }
        if (regionType === descRegionTypeEnum.site) {
          return quoteObjectEnum.site
        }
      }
      const newRow = {
        batchNo: this.quoteId,
        targetType: getTargetType(),
        targetCodeList: regionType === '0' ? ['0'] : dataList.map(item => item.code || item.id),
        targetNameList: regionType === '0' ? ['全国'] : dataList.map(item => item.name || item.label),
        ruleType
      }

      const res = await addBagThrowTarget(newRow)
      if (!res.status) return
      this.getTableData(true)
      this.getCombineInfo(this.tableData)
    },
    getCombineInfo(tableData) {
      this.spanArr = getSpanPosition(tableData, ['targetCode', 'ruleType'])
    },
    // 合并单元格
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      // 根据对象名称objectCode字段进行合并
      const spanColumns = this.isEdit ? [0, 1, 2, 3, 6] : [0, 1, 2]
      if (spanColumns.includes(columnIndex)) {
        const arr = this.spanArr
        for (let i = 0; i < arr.length; i++) {
          if (rowIndex === arr[i][0]) {
            return {
              rowspan: arr[i].length,
              colspan: 1
            }
          }
        }
        return {
          rowspan: 0,
          colspan: 0
        }
      }
    },
    handleEndWeightChange(isDel, row, index) {
      // 更新合并单元格
      this.$nextTick(async () => {
        this.tableData = await handleWeightRangeData({
          tableData: this.tableData,
          row,
          index,
          maxValue: 100,
          isDel,
          startKey: 'errorRateStart',
          endKey: 'errorRateEnd',
          hasGroup: true,
          groupKeys: ['targetCode', 'ruleType']
        })
        this.getCombineInfo(this.tableData)
        // 保存数据
        await this.saveTableData()
      })
    },
    handleAllSelected(val) {
      this.tableData.forEach(item => {
        item.isSelected = val
      })
      this.groupedSelections = this.tableData
    },
    handleItemChecked(val, row, index) {
      const groupKeys = ['targetCode', 'ruleType', 'id']
      // 查找到所有的groupIndexes
      const rowValueKeys = groupKeys.map(key => row[key]).join('')
      const tempGroupedSelections = []
      this.tableData.forEach(item => {
        const valueKeys = groupKeys.map(key => item[key])
        const uniqueValue = valueKeys.join('')
        if (rowValueKeys === uniqueValue) {
          item.isSelected = val
        }
        if (item.isSelected) {
          tempGroupedSelections.push(item)
        }
      })
      this.groupedSelections = tempGroupedSelections
      // 判断全选
      this.isAllSelected = !this.tableData.some(item => !item.isSelected)
    },
    handleBatchSet() {
      if (!this.groupedSelections.length) return this.$message.warning('请先选择要设置的行')
      this.$refs.batchSetFormRef && this.$refs.batchSetFormRef.show()
    },
    // 批量设置
    async handleBatchData({ tableData, executeStartDate, executeEndDate }) {
      // 获取当前选中的行
      const selectedRows = this.groupedSelections
      // 按照分组后的数据进行设置['targetCode', 'ruleType']
      const groupKeys = ['targetCode', 'ruleType']
      const groupIndexes = getGroupIndexes(selectedRows, groupKeys)

      // 只获取每组的第一行数据
      const firstRowsOfGroups = []
      Object.values(groupIndexes).forEach(indexes => {
        if (indexes.length > 0) {
          firstRowsOfGroups.push(selectedRows[indexes[0]])
        }
      })

      // 处理多段数据
      const processedTableData = []
      // 对每个选中的第一行应用所有段的数据
      firstRowsOfGroups.forEach(row => {
        tableData.forEach(segment => {
          processedTableData.push({
            ...row,
            errorRateStart: segment.errorRateStart,
            errorRateEnd: segment.errorRateEnd,
            coefficient: segment.coefficient,
            effectiveTimeDesc: executeStartDate,
            expireTimeDesc: executeEndDate
          })
        })
      })

      // 先移除选中的行
      const remainingRows = this.tableData.filter(
        row =>
          !selectedRows.some(selected => selected.targetCode === row.targetCode && selected.ruleType === row.ruleType)
      )

      // 添加处理后的新行
      this.tableData = [...remainingRows, ...processedTableData]
      const selectedIds = this.groupedSelections.map(item => item.id)
      this.clearSelection(selectedIds)

      this.$nextTick(() => {
        this.getCombineInfo(this.tableData)
      })
      // 提交数据
      await this.saveTableData()
      this.getTableData(true)
    },
    clearSelection(selectedIds) {
      if (!Array.isArray(selectedIds) || !selectedIds.length) return
      this.tableData.forEach(item => {
        if (selectedIds.includes(item.id)) {
          item.isSelected = !item.isSelected
        }
      })
    },
    // 对象查询
    async tableAjax(pager) {
      const { pageNum, pageSize } = pager
      let params = {
        pageSize,
        currentPage: pageNum,
        batchNo: this.batchNo,
        ...this.formData
      }
      if (this.modifyType === 'add') {
        params = {
          ...params,
          batchNo: this.quoteId
        }
      }
      const res = await queryPackageRuleTarget(params)

      const list =
        res.result.list.map(item => ({
          ...item,
          effectiveTimeDesc: item.effectiveTimeDesc || '',
          expireTimeDesc: item.expireTimeDesc === '长期' ? '' : item.expireTimeDesc,
          isSelected: false
        })) || []
      this.tableData = list
      this.getCombineInfo(this.tableData)

      return { rows: list || [], total: res.result.totalRow || 0 }
    },
    // 报价导入
    handleImport() {
      this.$refs.refImportSheet && this.$refs.refImportSheet.open('volumeDimensional')
    },
    async handleDelete(row) {
      if (!row.id) return
      const params = {
        batchNo: this.quoteId,
        idsList: [row.id]
      }
      const res = await removeBagThrowTarget(params)
      if (!res.status) return
      this.getTableData(true)
    },
    // 根据单元格合并判断删除
    isShowDelete(index) {
      // 判断不是合并后数组的第一行就可以删除
      for (let i = 0; i < this.spanArr.length; i++) {
        // 如果当前行是某个合并单元格的第一行，则不能删除
        if (index === this.spanArr[i][0]) {
          return false
        }
      }
      return true
    },
    // 单个字段校验
    validateField(row, field) {
      const value = row[field]
      if (row.ruleType === quoteRuleTypeEnum.temp && field === 'expireTimeDesc' && !row[field]) {
        return true
      }
      if (row.ruleType === quoteRuleTypeEnum.long && field === 'expireTimeDesc' && !row[field]) {
        return false
      }
      if (value === undefined || value === null || value === '') {
        return true
      }

      return false
    },
    validate() {
      return new Promise((resolve, reject) => {
        // 没有数据时，直接返回
        if (!this.tableData.length) {
          this.$message.error('请检查数据是否填写完整')
          reject(false)
          return
        }

        // 使用some检查是否有任何数据不完整
        const hasError = this.tableData.some(item => {
          const { errorRateStart, errorRateEnd, ruleType, coefficient, effectiveTimeDesc, expireTimeDesc } = item
          // 检查必填字段
          if (errorRateStart === undefined || errorRateStart === null) {
            return true
          }

          if (errorRateEnd === undefined || errorRateEnd === null) {
            return true
          }

          if (coefficient === undefined || coefficient === null) {
            return true
          }

          // 判断是临时还是长期
          if (!effectiveTimeDesc) {
            return true
          }

          // 临时报价时，生效时间不能为空
          if (ruleType === quoteRuleTypeEnum.temp && !expireTimeDesc) {
            return true
          }

          return false
        })

        if (hasError) {
          reject(false)
          return
        }
        resolve(true)
      })
    },
    async saveTableData() {
      // 校验数据
      const valid = await this.validate()
      if (!valid) return Promise.resolve(false)
      const bagThrowEditDataList = []
      const tableData = cloneDeep(this.tableData)
      const groupKeys = ['targetCode', 'ruleType']
      // 获取当前组第一条数据
      const setGroupTime = (item, index) => {
        const groupIndexes = getGroupIndexes(tableData, groupKeys)
        const values = groupKeys.map(key => item[key])
        const uniqueValue = values.join('')
        const firstGroupRow = tableData[groupIndexes[uniqueValue][0]]

        const tempRow = index === groupIndexes[0] ? item : firstGroupRow
        const effectiveTime = dayjs(tempRow.effectiveTimeDesc).format('YYYY-MM-DD 00:00:00')
        const expireTime = tempRow.expireTimeDesc
          ? dayjs(tempRow.expireTimeDesc).format('YYYY-MM-DD 23:59:59')
          : '2099-12-31 23:59:59'
        return {
          effectiveTime,
          expireTime
        }
      }
      this.tableData.forEach((item, index) => {
        bagThrowEditDataList.push({
          ...item,
          // 根据index的值判断是否是当前组的第一条数据，是则设置开始和结束时间，不是则使用第一条数据的开始和结束时间
          effectiveTime: setGroupTime(item, index).effectiveTime,
          expireTime: setGroupTime(item, index).expireTime
        })
      })
      const params = {
        batchNo: this.quoteId,
        bagThrowEditDataList
      }
      const res = await modifyBagThrowTarget(params)
      return Promise.resolve(res.status)
    }
  }
}
</script>
<style scoped lang="scss">
.cell-row {
  align-items: center;
  display: inline-flex;
  width: 100%;
  .z-icon-delete {
    font-size: 16px;
    margin-left: 4px;
  }
}
.mg-r8 {
  margin-right: 8px;
}
.table-cell {
  align-items: center;
  display: flex;
  justify-content: center;
  width: calc(100% - 16px);
  .z-icon-edit {
    margin-left: 6px;
  }
  &.startRate-cell {
    width: calc(100% - 30px);
  }
  .cell-divider {
    flex-shrink: 0;
    padding: 0 6px;
  }

  .z-input-number input {
    width: 85px;
  }
}
.is-left {
  box-sizing: border-box;
  overflow: hidden;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%;
  word-break: break-all;
}
::v-deep {
  .page-container {
    height: 100%;
    margin-bottom: 0;
  }
  .zs-page--stretch {
    height: 100%;
    margin: 0;
    min-height: 500px;
  }
  .z-tag {
    margin-right: 8px;
  }
}
.comp-batchAddObject {
  ::v-deep {
    .z-drawer__body {
      margin-bottom: 40px;
      overflow: auto;
      padding: 12px;
    }

    .z-drawer__footer {
      align-items: center;
      display: flex;
      height: 40px;
      justify-content: center;
    }
  }
}
.z-input--small.error,
.z-input-number--small.error {
  ::v-deep .z-input__inner {
    border: 1px solid red;
    border-color: red;
  }
}
</style>
